package com.sparkflow.mysqlbinlog.clickhousesync.utils;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * @Description: 数据josn序列化和反序列化工具类
 * @Author: Mr_xiaoZH
 */
public class JsonUtil {

    private static final String STANDARD_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_PATTERN = "yyyy-MM-dd";
    private static final String TIME_PATTERN = "HH:mm:ss";

    private static ObjectMapper objectMapper = new ObjectMapper();

    static{
        //初始化JavaTimeModule
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        //处理LocalDateTime
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(STANDARD_PATTERN);
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
        //处理LocalDate
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
        //处理LocalTime
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN);
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
        //注册时间模块, 支持支持jsr310
        objectMapper.registerModule(javaTimeModule);
        //在序列化一个空对象时时不抛出异常
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //忽略无法转换的对象
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        //设置序列化是忽略null值属性
//        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    /**
      * @description: 对象序列化为字符串
    　* @param  [value]
    　* @return java.lang.String
    　* @throws
    　* @date 2020/10/27 15:05
    　*/
    public static String jsonSerialization(Object value){
        if(value == null){
            return null;
        }
        try{
            return objectMapper.writeValueAsString(value);
        }catch (Exception e){
            throw new RuntimeException("解析对象错误");
        }
    }

    /**
      * @description: json字符串反序列化为对象
    　* @param  [json, clazz]
    　* @return T
    　* @throws
    　* @date 2020/10/27 15:06
    　*/
    public static <T> T jsonDeserialization(String json, Class<?> clazz){
        if(StringUtils.isBlank(json)){
            return null;
        }
        try{
            return (T)objectMapper.readValue(json, clazz);
        }catch (Exception e) {
            throw new RuntimeException("反序列化对象错误");
        }
    }

    /**
      * @description: json字符串反序列为集合对象
    　* @param  [json, collectionClass, elementClasses]
    　* @return T
    　* @throws
    　* @date 2020/10/27 15:06
    　*/
    public static <T> T jsonDeserialization(String json, Class<?> collectionClass, Class<?>... elementClasses){
        if(StringUtils.isBlank(json)){
            return null;
        }
        try{
            JavaType javaType = getJavaType(collectionClass, elementClasses);
            try {
                return objectMapper.readValue(json, javaType);
            } catch (com.fasterxml.jackson.core.JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }catch (Exception e){
            throw new RuntimeException("反序列化对象错误");
        }
    }

    private static JavaType getJavaType(Class<?> collectionClass, Class<?>... elementClasses){
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }

}
